//
//  CommonFunctions.swift
//  imprint
//
//  Created by 小柠檬🍋 on 2025/1/11.
//

import Foundation
import UIKit
import Photos
import LeanCloud
import UIKit
import SwiftUI



func showToast(_ text: String) {
    ToastManager.shared.show(message: text, duration: 2)
}

func showLoadPopup() {
    DispatchQueue.main.async {
        LoadingWindow.shared.show()
    }
}

func hideLoadPopup() {
    DispatchQueue.main.async {
        LoadingWindow.shared.hide()
    }
}

func showLoginPopup() {
    SwiftEntryKitWrapper.showBottomPopup { dismiss in
        LoginView() {
            dismiss()
        }
    }
}

//本地系统通知
func showLocalNotification(_ title:String, _ subtitle:String) {
    DispatchQueue.main.async {
        LocalNotificationManager.shared.cancelAllNotifications()
        LocalNotificationManager.shared.scheduleNotification(title: title, subtitle: subtitle)
    }
}

//排除字段 自定义反射
func doExcluded(subject: Any, excluded: Set<String>) -> [String?: Any?] {
    var properties: [String: Any] = [:]
    let mirror = Mirror(reflecting: subject)
    for (label, value) in mirror.children {
        if !excluded.contains(label!) {
            properties[label!] = value
        }
    }
    return properties
}

func getDeviceId() -> String {
    return UIDevice.current.identifierForVendor?.uuidString ?? ""
}


//字典转为为jsonData
func toJsonData(dict: [String: Any])  -> Data? {
    let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: [])
    return jsonData
}

/// 数组转为 JSON Data（支持任意元素类型的数组，只要元素是JSON合法类型）
func toJsonData(array: [Any]) -> Data? {
    try? JSONSerialization.data(withJSONObject: array, options: [])
}

//jsonData 转化为 String
func toString(jsonData: Data) -> String? {
    return String(data: jsonData, encoding: .utf8)
}

//jsonData 转化为 字典
func toDict(jsonData: Data) -> [String: Any]? {
    if let jsonDictionary = try? JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
        return jsonDictionary
    } else {
        return [:]
    }
}

//对象 转化为 字典
func toDict(_ object: Codable) -> [String: Any]? {
    do { let encoder = JSONEncoder()
        let data = try encoder.encode(object)
        return toDict(jsonData: data)
    } catch{
        return nil
    }
    
}

//对象 转化为 data
func toData(_ object: Codable) -> Data? {
    do {
        let encoder = JSONEncoder()
        let data = try encoder.encode(object)
        return data
    } catch{
        return nil
    }
    
}

//对象 转化为 data
func toData(_ object: Encodable) -> Data? {
    do {
        let encoder = JSONEncoder()
        let data = try encoder.encode(object)
        return data
    } catch{
        return nil
    }
    
}

//字典直接转化为json
func toJson(dict: [String: Any])-> String {
    guard let data = toJsonData(dict: dict) else {
        return ""
    }
    return toString(jsonData: data) ?? ""
}

/// 2. 字符串数组（[String]）转 JSON 字符串
func toJson(array: [String]) -> String {
    // 数组转 JSON 数据（逻辑与字典一致，复用 toJsonData 方法）
    guard let jsonData = toJsonData(array: array) else {
        showLog("字符串数组转 JSON 失败：数据格式异常")
        return ""
    }
    // 转字符串
    return toString(jsonData: jsonData) ?? ""
}

//

//实体类转换为json
func toJson(_ object: Codable) -> String? {
    let encoder = JSONEncoder()
    encoder.outputFormatting = .prettyPrinted // 可选：美化输出
    if let jsonData = try? encoder.encode(object),
       let jsonString = String(data: jsonData, encoding: .utf8) {
        return jsonString
    }
    return nil
}

//字典转换为实体类
func fromJson<T: Codable>(_ dict: [String: Any], _ modeType: T.Type) throws -> T? {
    let json = toJson(dict: dict)
    return try fromJson(json, modeType)
}

//json转换为实体类
func fromJson<T: Codable>(_ json: String?, _ modeType: T.Type) throws -> T? {
    if json == nil {
        throw MyError.getJsonFaild
    }
    let data = Data(json!.utf8)
    let decoder = JSONDecoder()
    
    do {
        return try decoder.decode(T.self, from: data)
    } catch let decodingError as DecodingError {
        switch decodingError {
        case .keyNotFound(let key, let context):
            showLog("json", "未找到键 \(key.stringValue)，\(modeType.self)，上下文: \(context.debugDescription)")
        case .valueNotFound(let type, let context):
            showLog("json", "未找到 \(type) 类型的值，上下文: \(context.debugDescription)")
        case .typeMismatch(let type, let context):
            showLog("json", "类型不匹配:\(modeType)，期望 \(type) 类型，上下文: \(context.debugDescription)")
        case .dataCorrupted(let context):
            showLog("json", "数据损坏，上下文: \(context.debugDescription)")
        @unknown default:
            showLog("json", "未知的解码错误: \(decodingError.localizedDescription)")
        }
        throw MyError.getJsonFaild
    } catch {
        showLog("其他错误: \(error.localizedDescription)")
        throw MyError.getJsonFaild
    }
}

//保存相册
func savePhoto(data:Data){
    if let image = UIImage(data: data) {
        // 请求相册访问权限（这里应该在实际尝试保存之前进行，并且只请求一次）
        PHPhotoLibrary.requestAuthorization { status in
            switch status {
            case .authorized:
                PHPhotoLibrary.shared().performChanges({
                    PHAssetChangeRequest.creationRequestForAsset(from: image)
                }) { success, error in
                    if success {
                        showToast("图片成功保存到相册")
                    } else {
                        showToast("保存图片到相册失败")
                    }
                }
            default:
                showToast("没有相册权限")
            }
        }
    }
}

/**
 * 获取在线时间
 * 单位为秒
 */
func getNetTime() async throws -> TimeInterval {
    let url = URL(string: "https://www.baidu.com")! // 创建 URL 对象
    var request = URLRequest(url: url)
    request.httpMethod = "HEAD" // 使用 HEAD 请求，只获取头部信息，减少数据传输
    
    do {
        let (_, response) = try await URLSession.shared.data(for: request)
        if let httpResponse = response as? HTTPURLResponse, let date = httpResponse.value(forHTTPHeaderField: "Date") {
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz"
            if let serverDate = dateFormatter.date(from: date) {
                // 将秒转换为毫秒
                return serverDate.timeIntervalSince1970
            }
        }
    } catch {
    }
    return Date().timeIntervalSince1970
}

func getNetTimeLocal() -> TimeInterval {
    return Date().timeIntervalSince1970
}

var curTime: TimeInterval = 0

func getCurTime() -> TimeInterval{
    if curTime == 0 {
        curTime = getNetTimeLocal()
    }
    return curTime
}

/**
 * 获取秒
 */
func getSecond(time: Int64) -> TimeInterval {
    if (String(time).count <= 10) {
        return TimeInterval(time)
    }
    return TimeInterval(time / 1000);
}

/**
 * 获取秒
 */
func getSecond(time: TimeInterval) -> TimeInterval {
    if (String(Int64(time)).count <= 10) {
        return time
    }
    return time / 1000;
}

/**
 * 获取毫秒
 */
func getMillisecond(_ time: TimeInterval) -> Int64 {
    if (String(Int64(time)).count <= 10) {
        return Int64(time * 1000)
    }
    return Int64(time);
}

//音频hex文本 转换为Data可播放
func hexStringToData(_ hexString: String?) -> Data? {
    if let hexString = hexString {
        let trimmedString = hexString.replacingOccurrences(of: " ", with: "")
        guard trimmedString.count % 2 == 0 else { return nil }
        
        var data = Data()
        var index = trimmedString.startIndex
        while index < trimmedString.endIndex {
            let nextIndex = trimmedString.index(index, offsetBy: 2)
            let byteString = String(trimmedString[index..<nextIndex])
            guard let byte = UInt8(byteString, radix: 16) else { return nil }
            data.append(byte)
            index = nextIndex
        }
        return data
    } else {
        return nil
    }
}

func requestPhotoLibraryPermission() {
    PHPhotoLibrary.requestAuthorization { status in
        switch status {
        case .authorized:
            showLog("已授权相册访问")
        case .denied, .restricted, .notDetermined:
            showLog("未授权相册访问")
            // 可以提示用户去设置中开启权限
        case .limited: break
            
        @unknown default:
            break
        }
    }
}

// 定义一个函数来获取字符串的拼音首字母
func getPinyinInitials(_ string: String) -> String {
    var initials = ""
    for char in string {
        let charString = String(char)
        let cfString = NSMutableString(string: charString) as CFMutableString
        
        // 转换为带音标的拼音
        CFStringTransform(cfString, nil, kCFStringTransformMandarinLatin, false)
        // 去掉音标
        CFStringTransform(cfString, nil, kCFStringTransformStripDiacritics, false)
        
        let pinyin = cfString as String
        if let firstLetter = pinyin.uppercased().first {
            initials.append(firstLetter)
        }
    }
    return initials
}

//图片cdn处理
func convertCdn(_ url : String?) -> String {
    let realUrl = url?.replacingOccurrences(of: "http://aiyuxm.com", with: "http://cdn.aiyuxm.com")
    let realUrl2 = realUrl?.replacingOccurrences(of: "https://aiyuxm.com", with: "https://cdn.aiyuxm.com") ?? ""
    return realUrl2
}

func formatPrice(_ price: Double) -> String {
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.minimumFractionDigits = 0
    formatter.maximumFractionDigits = 2
    return formatter.string(from: NSNumber(value: price)) ?? ""
}

func contactWx() {
    // 复制微信号到剪贴板
    showToast("微信号已经复制成功")
    UIPasteboard.general.string = "aiyukefu"
    // 尝试打开微信
    if let wechatURL = URL(string: "weixin://") {
        if UIApplication.shared.canOpenURL(wechatURL) {
            UIApplication.shared.open(wechatURL)
        } else {
            showToast("未安装微信应用")
        }
    }
}

func contactQQ() {
    let qqNumber = "1218968265"
    let urlString = "mqq://im/chat?chat_type=wpa&uin=\(qqNumber)&version=1&src_type=web"
    guard let url = URL(string: urlString) else { return  }
    
    if UIApplication.shared.canOpenURL(url) {
        UIApplication.shared.open(url)
    } else {
        showToast("未安装QQ")
    }
}

func contactQQGroup(groupUin: String, key: String) {
    // 注意：原始 Objective-C 代码中使用了硬编码参数，这里改为使用传入参数
    let urlString = String(
        format: "mqqapi://card/show_pslcard?src_type=internal&version=1&uin=%@&authSig=%@&card_type=group&source=external&jump_from=webapi",
        groupUin,
        key
    )
    
    guard let url = URL(string: urlString) else {
        showToast("未安装QQ")
        return
    }
    
    if UIApplication.shared.canOpenURL(url) {
        UIApplication.shared.open(url)
    } else {
        showToast("未安装QQ")
    }
}

func copyClipboard(_ str: String?) {
    UIPasteboard.general.string = str
}

func startCountdown(_ second: TimeInterval, completion: @escaping () -> Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + second) {
        completion()
    }
}


func getAppVersionAndBuild() -> (version: String, build: String) {
    guard let infoDictionary = Bundle.main.infoDictionary else {
        return ("Unknown", "Unknown")
    }
    
    let version = infoDictionary["CFBundleShortVersionString"] as? String ?? "Unknown"
    let build = infoDictionary["CFBundleVersion"] as? String ?? "Unknown"
    
    return (version, build)
}

//版本号：如111
func getAppVersion() -> Int {
    let curVersion = getAppVersionAndBuild().version.stringValue.formatVersion()
    return curVersion
}


/// 封装方法：根据完整文字和需要加粗的部分自动匹配位置并加粗
func highlightAndBoldText(fullText: String, boldTexts: [String], size: CGFloat) -> AttributedString {
    let attributedString = NSMutableAttributedString(string: fullText)
    
    // 遍历所有需要加粗的文字
    for boldText in boldTexts {
        if let range = fullText.range(of: boldText) {
            let nsRange = NSRange(range, in: fullText)
            attributedString.addAttributes(
                [.font: UIFont.systemFont(ofSize: size, weight: .bold), // 使用最粗字体
                 .foregroundColor: UIColor.bgNormalText // 设置加粗文字颜色
                ],
                range: nsRange
            )
        }
    }
    
    return AttributedString(attributedString)
}

/// 封装方法：文字高亮与加粗
/// - Parameters:
///   - fullText: 完整文本
///   - targetTexts: 需要处理的文字数组
///   - color: 高亮颜色（为nil时不改变颜色）
///   - isBold: 是否需要加粗
///   - highlightAll: 是否高亮所有匹配内容（true：全部高亮，false：仅首次出现）
func highlightText(
    fullText: String,
    colorTexts: [String],
    color: UIColor? = nil,
    isBold: Bool = false,
    highlightAll: Bool = false
) -> AttributedString {
    let attributedString = NSMutableAttributedString(string: fullText)
    
    for targetText in colorTexts {
        var searchRange = NSRange(location: 0, length: fullText.utf16.count)
        var foundRange: NSRange?
        
        repeat {
            // 查找目标文本位置
            foundRange = (fullText as NSString).range(of: targetText, options: [], range: searchRange)
            
            if let range = foundRange, range.location != NSNotFound {
                // 准备需要添加的属性
                var attributes: [NSAttributedString.Key: Any] = [:]
                
                // 添加颜色属性（如果有指定颜色）
                if let color = color {
                    attributes[.foregroundColor] = color
                }
                
                // 添加加粗属性（如果需要加粗）
                if isBold {
                    // 获取原有字体并设置为粗体
                    let originalFont = UIFont.systemFont(ofSize: UIFont.systemFontSize)
                    let boldFont = UIFont.boldSystemFont(ofSize: originalFont.pointSize)
                    attributes[.font] = boldFont
                }
                
                // 应用属性
                attributedString.addAttributes(attributes, range: range)
                
                if !highlightAll {
                    // 仅首次匹配则退出循环
                    break
                } else {
                    // 全部匹配则更新搜索范围
                    searchRange.location = range.location + range.length
                    searchRange.length = fullText.utf16.count - searchRange.location
                }
            }
        } while highlightAll && foundRange?.location != NSNotFound
    }
    
    return AttributedString(attributedString)
}

// 验证URL有效性
func isValidUrl(_ urlString: String) -> Bool {
    guard let url = URL(string: urlString) else {
        return false
    }
    // 检查是否为HTTP/HTTPS协议的网络URL
    return url.scheme == "http" || url.scheme == "https"
}

//关闭软键盘
func hideKeyboard() {
    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}

//是否审核版本
func isExamine() -> Bool {
    return configManager.getConfig().isExamineVersion()
}

func iOS26() -> Bool {
    if #available(iOS 26.0, *) {
        return true
    } else {
        return false
    }
}
